package com.itlong.cloud.smartcard;

import com.alibaba.fastjson.JSON;
import com.itlong.cloud.POJO.DTO.smartcard.*;
import com.itlong.cloud.POJO.PO.*;
import com.itlong.cloud.POJO.VO.operate.OperateProjectDetailVO;
import com.itlong.cloud.POJO.VO.property.AppUserGetDeviceAuthVO;
import com.itlong.cloud.POJO.VO.property.PropertyEquipGetVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.enumerate.*;
import com.itlong.cloud.equip.property.IPropertyDeviceAuthServiceClient;
import com.itlong.cloud.equip.property.IPropertyEquipServiceClient;
import com.itlong.cloud.equip.smartcard.ISmartCardDeviceServiceClient;
import com.itlong.cloud.equip.smartcard.ISmartCardEquipRecordServiceClient;
import com.itlong.cloud.project.operate.IOperateProjectServiceClient;
import com.itlong.cloud.project.smartcard.ISmartCardSyncDataServiceClient;
import com.itlong.cloud.user.smartcard.ISmartCardUserInfoServiceClient;
import com.itlong.cloud.utils.date.DateUtil;
import com.itlong.cloud.utils.random.LogicIdUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;

/**
 * <desc>
 *      与旺龙一卡通对接-解析存于push表中的数据的定时任务
 * </desc>
 *
 * @createDate 2017-11-06
 */
@EnableScheduling // 启用定时任务
@RestController
public class SmartCardAnalysisPushDataTimedTask {

    private static Logger LOG = LoggerFactory.getLogger(SmartCardAnalysisPushDataTimedTask.class);

    private static boolean firstStart = true;  //首次启动

    private boolean needRefeshUserRedisByProjectId; //是否需要按项目通知刷新用户redis,(有设备或楼层对应表变更时)

    @Autowired
    ISmartCardSyncDataServiceClient iSmartCardSyncDataServiceClient;

    @Autowired
    IPropertyEquipServiceClient iPropertyEquipServiceClient;

    @Autowired
    ISmartCardDeviceServiceClient iSmartCardDeviceServiceClient;

    @Autowired
    ISmartCardEquipRecordServiceClient iSmartCardEquipRecordServiceClient;

    @Autowired
    ISmartCardUserInfoServiceClient iSmartCardUserInfoServiceClient;

    @Autowired
    IOperateProjectServiceClient iOperateProjectServiceClient;  //项目信息获取对象（主要用于获取项目是否启动云对讲）

    @Autowired
    IPropertyDeviceAuthServiceClient iPropertyDeviceAuthServiceClient;  //用户设备权限操作对象

    /**
     * <desc>
     *      与旺龙一卡通对接-解析存于push表中的数据
     * <desc/>
     *
     * @param
     * @return
     * @author zhangs
     * @createDate 2017/10/31
     */
    @Scheduled(cron = "0/10 * * * * ?")  //每10s执行一次
//    @Scheduled(cron = "0 */10 * * * ?")  //每10分钟执行一次
    //    @Scheduled(cron = "0 */10 * * * ?")  //每10分钟执行一次
    public void scheduler() {

        if (!beforeScheduler()){
            return;
        }
        try {
            this.doScheduler();

        } catch (Exception e) {
            LOG.error(String.format(
                    "【定时任务_与旺龙一卡通对接-解析存于push表中的数据_scheduler()出错】"), e);
        }
        finally {
            this.AfterScheduler();
        }
    }


    /**
    * <desc>
    *    执行一卡通同步数据分析的任务.
    * </desc>
    *
    * @return xx
    * @author LewisLouis
    * @createDate 2017-12-29
    */
    private void doScheduler() throws Exception {

//        LOG.info("【定时任务】解析一卡通同步到云端的数据-开始执行，有数据需要解析,当前时间：" +
//                DateUtil.format(Calendar.getInstance(), "yyyy-MM-dd HH:mm:ss"));
        //查询有数据需要解析的push表
        List<TimeTaskPushAnalysisPO> timeTaskPushAnalysisPOS =
                iSmartCardSyncDataServiceClient.getPushTableName(PlatformConstants.HAS_SMART_CARD_PUSH_DATA_FOR_ANALYSIS);
        if ((null == timeTaskPushAnalysisPOS) || (timeTaskPushAnalysisPOS.isEmpty())){
            //没有查找到一卡通push数据到云端，本次任务结束
            LOG.info("未查询到一卡通推送到云端到数据");
            return;
        }

        //遍历，查询各push表中需要解析的数据
        for (TimeTaskPushAnalysisPO timeTaskPushAnalysisPO : timeTaskPushAnalysisPOS) {
            //有需要解析数据的push表名
            String tableName = timeTaskPushAnalysisPO.getTableName();
            //查询push中未解析的数据
            List<SmartCardPushPO> smartCardPushPOS =
                    iSmartCardSyncDataServiceClient.getUnresolvedPushData(tableName);

            if ((null == smartCardPushPOS) || (smartCardPushPOS.isEmpty())){
                //将数据已解析的push表状态置已处理
                timeTaskPushAnalysisPO.setMark(PlatformConstants.NO_SMART_CARD_PUSH_DATA_FOR_ANALYSIS);
                iSmartCardSyncDataServiceClient.updateTimeTaskPushStatus(timeTaskPushAnalysisPO);
               continue;
            }

            String projectId = smartCardPushPOS.get(0).getProjectId();
            needRefeshUserRedisByProjectId = false;

            //获取对应项目信息。判断是否使用云对讲
            OperateProjectDetailVO projectInfo = iOperateProjectServiceClient.getDetail(projectId);
            if (projectInfo == null){
                //将数据已解析的push表状态置已处理
                timeTaskPushAnalysisPO.setMark(PlatformConstants.NO_SMART_CARD_PUSH_DATA_FOR_ANALYSIS);
                iSmartCardSyncDataServiceClient.updateTimeTaskPushStatus(timeTaskPushAnalysisPO);
                LOG.info(String.format("项目Id为：%s的项目信息不存在,跳过同步信息:%s 的处理",projectId,JSON.toJSONString(smartCardPushPOS)));
                continue;
            }

            try {
                if (!handleAnalysisData(smartCardPushPOS,projectInfo)){
                    continue;
                }
            } finally {
                if (needRefeshUserRedisByProjectId){
                    iSmartCardDeviceServiceClient.sendMessageForDeviceChanged(projectId);
                }
            }

            //查询push中剩下的未解析的数据（可能是未能一次处理完的或者新产生的）
            List<SmartCardPushPO> leftSmartCardPushPOS =  iSmartCardSyncDataServiceClient.getUnresolvedPushData(tableName);

            if ((null != leftSmartCardPushPOS) && (leftSmartCardPushPOS.size() <= 0)){
                //将数据已解析的push表状态置已处理
                timeTaskPushAnalysisPO.setMark(PlatformConstants.NO_SMART_CARD_PUSH_DATA_FOR_ANALYSIS);
                iSmartCardSyncDataServiceClient.updateTimeTaskPushStatus(timeTaskPushAnalysisPO);
            }
        }
    }

    /**
    * <desc>
    *    执行任务前的状态检查.
    * </desc>
    * @return 是否可进行任务执行
    * @author LewisLouis
    * @createDate 2017-12-29
    */
    private boolean beforeScheduler(){
        SmartCardSyncTaskStatusDTO taskStatus = iSmartCardSyncDataServiceClient.getSmartCardSyncTaskStatus();
        if (taskStatus != null){
            int hasSkipCount = taskStatus.getRunningSkipCount() == null?0:taskStatus.getRunningSkipCount();
            if ((!firstStart) && taskStatus.isTaskRunnig() && (hasSkipCount <= PlatformConstants.SMARTCARD_TASK_SKIP_MAX_COUNT)){
                LOG.info("【定时任务】解析一卡通同步到云端的数据已正在执行，本次放弃执行：" +
                        DateUtil.format(Calendar.getInstance(), "yyyy-MM-dd HH:mm:ss"));
                hasSkipCount++;
                taskStatus.setRunningSkipCount(hasSkipCount);
                iSmartCardSyncDataServiceClient.setSmartCardSyncTaskStatus(taskStatus);
                return false;  //没有任何一卡通push数据到云端，本次任务结束
            }
            firstStart = false;
            if (!taskStatus.isHasPushDataNeedToHandle()){
//                LOG.info("【定时任务】解析一卡通同步到云端的数据-开始执行，没有数据需要解析,跳过本次执行，当前时间：" +
//                        DateUtil.format(Calendar.getInstance(), "yyyy-MM-dd HH:mm:ss"));
                return false;  //没有任何一卡通push数据到云端，本次任务结束
            }
            taskStatus.setTaskRunnig(true);
            taskStatus.setRunningSkipCount(0);
            iSmartCardSyncDataServiceClient.setSmartCardSyncTaskStatus(taskStatus);
        }
        return true;
    }

    
    /**
    * <desc>
    *     当次任务结束时.进行状态检查
    * </desc>
    *
    * @return
    * @author LewisLouis
    * @createDate 2017-12-29
    */
    private void AfterScheduler(){
        //再次检查是否有新的Push数据出现
        try {
            List<TimeTaskPushAnalysisPO>timeTaskPushAnalysisPOS =
                    iSmartCardSyncDataServiceClient.getPushTableName(PlatformConstants.HAS_SMART_CARD_PUSH_DATA_FOR_ANALYSIS);
            boolean hasGloalPushData = (null != timeTaskPushAnalysisPOS) && (!timeTaskPushAnalysisPOS.isEmpty());
            SmartCardSyncTaskStatusDTO taskStatusDTO = iSmartCardSyncDataServiceClient.getSmartCardSyncTaskStatus();
            if (taskStatusDTO != null){
                taskStatusDTO.setHasPushDataNeedToHandle(hasGloalPushData);
                taskStatusDTO.setTaskRunnig(false);
                iSmartCardSyncDataServiceClient.setSmartCardSyncTaskStatus(taskStatusDTO);
            }
        } catch (Exception e) {
            LOG.error(String.format(
                    "【定时任务_与旺龙一卡通对接-检查定时任务状态出错】"), e);
        }
    }




    /**
     * <desc>
     *      与旺龙一卡通对接-整理解析存于push表的中的数据
     * <desc/>
     *
     * @param smartCardPushPOS push表中未解析的数据集
     * @return
     * @author zhangs
     * @createDate 2017/11/15
     */
    private boolean handleAnalysisData(List<SmartCardPushPO> smartCardPushPOS, OperateProjectDetailVO projectInfo) {


        //将同一张push表中的数据分类
        /*//地址信息
        List<SmartCardPushPO> pushTableAddressData = new ArrayList<>();
        //住户房间地址信息
        List<SmartCardPushPO> pushTableUserHouseData = new ArrayList<>();*/
        //设备信息
        try {
            List<SmartCardPushPO> pushTableEquipData = new ArrayList<>();
            //楼层映射表信息
            List<SmartCardPushPO> pushTableFloorData = new ArrayList<>();
            //通行记录信息
            List<SmartCardPushPO> pushTableRecordData = new ArrayList<>();
            //住户基本信息
            List<SmartCardPushPO> pushTableHouseHoldData = new ArrayList<>();
            //住户设备权限信息
            List<SmartCardPushPO> pushTableAuthData = new ArrayList<>();

            for (SmartCardPushPO smartCardPushPO : smartCardPushPOS) {

                Integer dataType = smartCardPushPO.getDataType();
                //LOG.error(String.format("发现一卡通推送给云端的：%s 数据需要解析..",SmartCardSyncDataTypeEnum.getByType(dataType).getDescription()));
                switch (SmartCardSyncDataTypeEnum.getByType(dataType)) {
                    case ADDRESS_DATA:
                        break;
                    case USER_HOUSE_DATA:
                        break;
                    case EQUIP_DATA:
                        pushTableEquipData.add(smartCardPushPO);
                        break;
                    case FLOOR_RELATION_DATA:
                        pushTableFloorData.add(smartCardPushPO);
                        break;
                    case PASS_RECORD_DATA:
                        pushTableRecordData.add(smartCardPushPO);
                        break;
                    case USER_BASIS_DATA:
                        pushTableHouseHoldData.add(smartCardPushPO);
                        break;
                    case USER_AUTH_DATA:
                        pushTableAuthData.add(smartCardPushPO);
                        break;
                }
            }

            if (!pushTableEquipData.isEmpty()) {
                this.handleAnalysisEquip(pushTableEquipData);

                //LOG.info(String.format("处理了一卡通推送给云端的设备信息：%d",pushTableEquipData.size()));
               // LOG.info(String.format("处理了一卡通推送给云端的设备信息：%s",JSON.toJSONString(pushTableEquipData)));
            }
            if (!pushTableFloorData.isEmpty()) {
                this.handleAnalysisFloorRelation(pushTableFloorData);
                //LOG.info(String.format("处理了一卡通推送给云端的楼层对应表信息：%d",pushTableFloorData.size()));
               // LOG.info(String.format("处理了一卡通推送给云端的楼层对应表信息：%s",JSON.toJSONString(pushTableFloorData)));
            }
            if (!pushTableRecordData.isEmpty()) {
               this.handleAnalysisPassRecord(pushTableRecordData);
                //LOG.info(String.format("处理了一卡通推送给云端的通行记录信息：%d",pushTableRecordData.size()));
                //LOG.info(String.format("处理了一卡通推送给云端的通行记录信息：%s",JSON.toJSONString(pushTableRecordData)));
            }
            if (!pushTableHouseHoldData.isEmpty()) {
                this.handleAnalysisUserBasisInfo(pushTableHouseHoldData,projectInfo);
                //LOG.info(String.format("处理了一卡通推送给云端的用户基本信息：%d",pushTableHouseHoldData.size()));
                //LOG.info(String.format("处理了一卡通推送给云端的用户基本信息：%s",JSON.toJSONString(pushTableHouseHoldData)));
            }
            if (!pushTableAuthData.isEmpty()) {
               this.handleAnalysisUserAuth(pushTableAuthData,projectInfo);
                //LOG.info(String.format("处理了一卡通推送给云端的用户权限信息：%s",pushTableAuthData.size()));
               // LOG.info(String.format("处理了一卡通推送给云端的用户权限信息：%s",JSON.toJSONString(pushTableAuthData)));
            }

            //将已处理的一卡通同步到云端到数据进行转移.
            this.movePushDataToColdTable(projectInfo.getProjectId());
        } catch (Exception e) {
            LOG.info(String.format("处理一卡通推送给云端的信息异常：%s",JSON.toJSONString(projectInfo)),e);
            return  false;
        }
        return  true;

    }

    /**
     * <desc>
     *    将已处理的一卡通同步到云端到数据进行转移.
     * </desc>
     *
     * @param projectId 项目编号
     * @return
     * @author LewisLouis
     * @createDate 2018-01-09
     */
    private void movePushDataToColdTable(String projectId){
        String tableName = String.format("%s%s",PlatformConstants.SMARTCARD_TABLENAME_PREFIX_PUSH,projectId);
        iSmartCardSyncDataServiceClient.movePushDataToColdTable(tableName);
    }

    /**
     * <desc>
     *      与旺龙一卡通对接-整理解析存于push表的中的设备信息数据
     * <desc/>
     *
     * @param pushTableEquipData 设备信息解析传输对象
     * @return
     * @author zhangs
     * @createDate 2017/11/15
     *
     * 一卡通上传的data数据格式示例：
     * [{"projectId":"05041276","deviceUnique":"0504127630010","modifyDate":"1505909016893","deviceName":"15312","deviceType":"3","dataOperType":3}]
     */
    private boolean handleAnalysisEquip(List<SmartCardPushPO> pushTableEquipData) {
        if (pushTableEquipData.isEmpty()) {
            return true;
        }
        String projectId = pushTableEquipData.get(0).getProjectId();
        //遍历，获取同步表中一卡通push的数据，按云端系统现有PO进行解析最后入库
        for (SmartCardPushPO smartCardPushPO :pushTableEquipData) {
            //同步的数据
            String syncData = smartCardPushPO.getSyncData();

            try {
                //解析
                SmartCardSyncDataPullEquipDTO smartCardSyncDataPullEquipDTO =
                        JSON.parseObject(syncData, SmartCardSyncDataPullEquipDTO.class);
                if (smartCardSyncDataPullEquipDTO == null) {
                    LOG.info(String.format("解析一卡通推送给云端的设备数据失败,%s",syncData));
                    continue;
                }
                Integer deviceType = smartCardSyncDataPullEquipDTO.getDeviceType();
                String deviceUnique = smartCardSyncDataPullEquipDTO.getDeviceUnique();
                String deviceName = smartCardSyncDataPullEquipDTO.getDeviceName();
                String deviceId = StringHandlerUtil.copySubStr(smartCardSyncDataPullEquipDTO.getDeviceUnique(),9,4);
               // String modifyDate = smartCardSyncDataPullEquipDTO.getModifyDate();
                //Date date = DateUtil.formatLong(Long.parseLong(modifyDate));
                SmartCardSyncDeviceInfoDTO smartCardSyncDeviceInfoDTO = new SmartCardSyncDeviceInfoDTO();
                smartCardSyncDeviceInfoDTO.setDeviceType(deviceType);
                smartCardSyncDeviceInfoDTO.setDeviceId(deviceId);
                smartCardSyncDeviceInfoDTO.setDeviceUnique(deviceUnique);
                smartCardSyncDeviceInfoDTO.setDeviceName(deviceName);
                smartCardSyncDeviceInfoDTO.setProjectId(projectId);
                String devProjectId = StringHandlerUtil.getProjectIdByDeviceUnique(deviceUnique);

                //设备Unique中的项目Id和当前数据的项目Id匹配时（防止一卡通在离线时随意更新项目导致设备与项目不匹配），才进行更新
                if (StringHandlerUtil.compareStrIgnoreCaseWithOutEmpty(devProjectId,projectId)){
                    String tableName = String.format("%s%s",PlatformConstants.SMARTCARD_TABLENAME_PREFIX_PULL,projectId);
                    if (this.isLatestData(tableName,smartCardPushPO)){
                        switch (SmartCardSyncDataOperTypeEnum.getByDataOperType(smartCardPushPO.getDataOperType())){
                            case ADD:
                            case UPDATE:
                                PropertyEquipGetVO propertyEquipGetVO = iPropertyEquipServiceClient.getByDeviceUnique(deviceUnique);
                                if (propertyEquipGetVO == null) {
                                    iSmartCardDeviceServiceClient.addDeviceInfo(smartCardSyncDeviceInfoDTO);
                                } else {
                                    iSmartCardDeviceServiceClient.updateDeviceInfo(smartCardSyncDeviceInfoDTO);
                                }
                                break;
                            default:
                                break;
                        }
                        needRefeshUserRedisByProjectId = true;
                    }

                } else {
                    LOG.info(String.format("一卡通同步到云端的设备：%s 不属于项目:%s，放弃处理!",deviceUnique,projectId));
                }

                //更新push表中已完成解析的数据的状态
                this.setSyncPushDataResolvedById(smartCardPushPO);

            } catch (Exception e) {
                LOG.info(String.format("处理一卡通推送给云端的设备数据失败,%s",syncData), e);
                continue;
            }

        }
        return true;
    }




    /**
     * <desc>
     *      与旺龙一卡通对接-整理解析存于push表的中的楼层映射表信息数据
     * <desc/>
     *
     * @param pushTableFloorRelationInfos 楼层映射表信息解析传输对象
     * @return
     * @author zhangs
     * @createDate 2017/11/15
     *
     * 一卡通上传的data数据格式示例：
     * {"deviceUnique": "2016062310001","logicalFloor": "1F","modifyDate": "1504835716608","naturalFloor": "1","dataOperType": 3,"terminalNum": "2"}
     */
    private boolean handleAnalysisFloorRelation(List<SmartCardPushPO> pushTableFloorRelationInfos) {
        if (pushTableFloorRelationInfos.isEmpty()) {
            return true;
        }
        String projectId = pushTableFloorRelationInfos.get(0).getProjectId();
        //遍历，获取同步表中一卡通push的数据，按云端系统现有PO进行解析最后入库
        for (SmartCardPushPO smartCardPushPO :pushTableFloorRelationInfos) {
            //同步的数据
            String syncData = smartCardPushPO.getSyncData();

            try {
                //解析
                SmartCardSyncDataFloorRelationDTO smartCardSyncDataFloorRelationDTO = JSON.parseObject(syncData, SmartCardSyncDataFloorRelationDTO.class);
                if (smartCardSyncDataFloorRelationDTO == null) {
                    LOG.info(String.format("解析一卡通推送给云端的楼层对应表失败,%s",syncData));
                    continue;
                }
                String tableName = String.format("%s%s",PlatformConstants.SMARTCARD_TABLENAME_PREFIX_PULL,projectId);
                if (this.isLatestData(tableName,smartCardPushPO)){
                    switch (SmartCardSyncDataOperTypeEnum.getByDataOperType(smartCardPushPO.getDataOperType())){
                        case ADD:
                        case UPDATE:
//                            String modifyDate = smartCardSyncDataFloorRelationDTO.getModifyDate();
//                            Date date = DateUtil.formatLong(Long.parseLong(modifyDate));
                            DeviceElevatorFloorConfigPO deviceElevatorFloorConfigPO = new DeviceElevatorFloorConfigPO();
                            BeanUtils.copyProperties(smartCardSyncDataFloorRelationDTO, deviceElevatorFloorConfigPO);
                            deviceElevatorFloorConfigPO.setTerminalFloor(smartCardSyncDataFloorRelationDTO.getTerminalNum());
                            Date date = new Date();
                            deviceElevatorFloorConfigPO.setTerminalFloor(deviceElevatorFloorConfigPO.getTerminalFloor().equals("0") ? "-" : deviceElevatorFloorConfigPO.getTerminalFloor());
                            deviceElevatorFloorConfigPO.setCreateTime(date);
                            deviceElevatorFloorConfigPO.setUpdateTime(date);
                            deviceElevatorFloorConfigPO.setStatus(DataStatusEnum.NORMAL.getType());
                            iSmartCardDeviceServiceClient.saveOrUpdatefloorConfig(deviceElevatorFloorConfigPO);

                            break;
                        default:
                            break;
                    }
                    needRefeshUserRedisByProjectId = true;
                }
                //更新push表中已完成解析的数据的状态
                this.setSyncPushDataResolvedById(smartCardPushPO);

            } catch (Exception e) {
                LOG.error(String.format("处理一卡通推送给云端的楼层对应表失败,%s",syncData),e);
                continue;
            }

        }

        return true;
    }

    /**
     * <desc>
     *      与旺龙一卡通对接-整理解析存于push表的中的住户信息数据
     * <desc/>
     *
     * @param pushTableUserBasisInfo 住户信息解析传输对象
     * @return
     * @author zhangs
     * @createDate 2017/11/15
     *
     * 一卡通上传的data数据格式示例：
     * [{"projectId": "05041276","userPhone": "18120583180","userName": "lili","cardNum": "000000","modifyDate": "1510132255199","dataOperType": 3}]
     */
    private boolean handleAnalysisUserBasisInfo(List<SmartCardPushPO> pushTableUserBasisInfo,OperateProjectDetailVO projectInfo) {
        if (pushTableUserBasisInfo.isEmpty()) {
            return true;
        }
        String projectId = pushTableUserBasisInfo.get(0).getProjectId();
        //遍历，获取同步表中一卡通push的数据，按云端系统现有PO进行解析最后入库
        for (SmartCardPushPO smartCardPushPO :pushTableUserBasisInfo) {
            //同步的数据
            String syncData = smartCardPushPO.getSyncData();
            try {
                //解析
                SmartCardSyncDataPullUserBasisInfoDTO smartCardSyncDataPullUserBasisInfoDTO = JSON.parseObject(syncData, SmartCardSyncDataPullUserBasisInfoDTO.class);
                if (smartCardSyncDataPullUserBasisInfoDTO == null) {
                    LOG.info(String.format("解析一卡通推送给云端的用户基本资料失败,%s",syncData));
                    continue;
                }

                String tableName = String.format("%s%s",PlatformConstants.SMARTCARD_TABLENAME_PREFIX_PULL,projectId);
                if (isLatestData(tableName,smartCardPushPO)){
                    switch (SmartCardSyncDataOperTypeEnum.getByDataOperType(smartCardPushPO.getDataOperType())){
                        case ADD:
                        case UPDATE:
                            //save或者update AppUserInfo和AppUserProject
                            iSmartCardUserInfoServiceClient.saveOrUpdateSmartCardUserBasisInfo(smartCardSyncDataPullUserBasisInfoDTO,
                                    projectId,
                                    projectInfo.getIsSmartCommunity());
                            break;
                        default:
                            break;
                    }
                }
                //更新push表中已完成解析的数据的状态
                this.setSyncPushDataResolvedById(smartCardPushPO);
            } catch (Exception e) {
                LOG.error(String.format("处理一卡通推送给云端的用户基本资料失败,%s",syncData), e);
                continue;
            }

        }
        return true;
    }

    /**
     * <desc>
     *      与旺龙一卡通对接-整理解析存于push表的中的住户设备权限信息数据
     * <desc/>
     *
     * @param pushTableUserAuthInfos 住户设备权限信息解析传输对象
     * @return
     * @author zhangs
     * @createDate 2017/11/15
     *
     * 一卡通上传的data数据格式示例：
     * [{"userPhone": "18120583107","userEmail":"xxxx@sina.com", "sysAuths": [
     *   {"deviceAuths": [{"deviceUnique": "0504127610003","auth": "4000000000000000000000000000"}],"deviceType": 1,"validDate": "4102382946000"},
     *   {"deviceAuths": [{"deviceUnique": "0504127620025","auth": "8"}],"deviceType": 2,"validDate": "4102382946000"}
     *   ],"dataOperType": 2,"modifyDate": "1506559767109"}]
     */
    private boolean handleAnalysisUserAuth(List<SmartCardPushPO> pushTableUserAuthInfos,OperateProjectDetailVO projectInfo) {
        if (pushTableUserAuthInfos.isEmpty()) {
            return false;
        }
        String projectId = pushTableUserAuthInfos.get(0).getProjectId();
        //遍历，获取同步表中一卡通push的数据，按云端系统现有PO进行解析最后入库
        for (SmartCardPushPO smartCardPushPO :pushTableUserAuthInfos) {
            //同步的数据
            String syncData = smartCardPushPO.getSyncData();

            try {
                //解析
                SmartCardSyncDataPullUserAuthDTO smartCardSyncDataPullUserAuthDTO = JSON.parseObject(syncData, SmartCardSyncDataPullUserAuthDTO.class);
                if (smartCardSyncDataPullUserAuthDTO == null) {
                    LOG.info(String.format("解析一卡通推送给云端的用户设备权限失败,%s",syncData));
                    continue;
                }
                String userPhone = smartCardSyncDataPullUserAuthDTO.getUserPhone();
                String userEmail = smartCardSyncDataPullUserAuthDTO.getUserEmail();
//                String modifyDate = smartCardSyncDataPullUserAuthDTO.getModifyDate();
                //修改时间
//                Date modify = DateUtil.formatLong(Long.parseLong(modifyDate));
//                Integer operateType = smartCardSyncDataPullUserAuthDTO.getOperateType().;
                List<SmartCardSyncDataSysDeviceAuthDTO> sysAuths = smartCardSyncDataPullUserAuthDTO.getSysAuths();
                if (sysAuths.isEmpty()) {
                    LOG.info(String.format("解析一卡通推送给云端的用户设备权限失败,没有设备权限.%s",syncData));
                    continue;
                }
                String tableName = String.format("%s%s",PlatformConstants.SMARTCARD_TABLENAME_PREFIX_PULL,projectId);
                if (isLatestData(tableName,smartCardPushPO)){
                    switch (SmartCardSyncDataOperTypeEnum.getByDataOperType(smartCardPushPO.getDataOperType())){
                        case ADD:
                        case UPDATE:
                            //住户设备权限数据集
                            List<AppUserGetDeviceAuthVO> appUserGetDeviceAuthVOS = new ArrayList<>();
                            //遍历单个住户设备权限数据
                            for (SmartCardSyncDataSysDeviceAuthDTO smartCardSyncDataSysDeviceAuthDTO :sysAuths) {
                                Integer deviceType = smartCardSyncDataSysDeviceAuthDTO.getDeviceType();
                                //有效期,13位时间戳
                                String validDate = smartCardSyncDataSysDeviceAuthDTO.getValidDate();
                                //有效时间
                                Date valid = DateUtil.formatLong(Long.parseLong(validDate));
                                List<SmartCardSyncDataSingleDevieAuthDTO> deviceAuths = smartCardSyncDataSysDeviceAuthDTO.getDeviceAuths();
                                if (deviceAuths.isEmpty()) {
                                    continue;
                                }
                                //遍历具体设备权限数据
                                for (SmartCardSyncDataSingleDevieAuthDTO smartCardSyncDataSingleDevieAuthDTO : deviceAuths) {
                                    AppUserGetDeviceAuthVO appUserGetDeviceAuthVO = new AppUserGetDeviceAuthVO();
                                    appUserGetDeviceAuthVO.setDeviceUnique(smartCardSyncDataSingleDevieAuthDTO.getDeviceUnique());
                                    appUserGetDeviceAuthVO.setDeviceType(String.valueOf(deviceType));
                                    if (PropertyEquipTypeEnum.ELEVATOR.getType() == deviceType) {
                                        String naturalFloor = StringHandlerUtil.getNaturalFloorsByAuthCode(smartCardSyncDataSingleDevieAuthDTO.getAuth());
                                        appUserGetDeviceAuthVO.setNaturalFloor(naturalFloor);
                                    }
                                    appUserGetDeviceAuthVOS.add(appUserGetDeviceAuthVO);
                                }
                            }

                            //保存或更新住户设备权限信息
                            SmartCardGetAppUserInfoDTO getAppUserInfoDTO = new SmartCardGetAppUserInfoDTO();
                            getAppUserInfoDTO.setProjectId(projectId);
                            getAppUserInfoDTO.setPhoneNum(userPhone);
                            getAppUserInfoDTO.setEmail(userEmail);
                            AppUserInfoPO appUserInfoPO = iSmartCardUserInfoServiceClient.getSmartCardAppUserInfo(getAppUserInfoDTO);
                            if (appUserInfoPO != null) {
                                String userId = appUserInfoPO.getUserId();
                                iPropertyDeviceAuthServiceClient.updateSmartCardUserDeviceAuth(
                                        projectId, userId, projectId, appUserGetDeviceAuthVOS);
                            } else {

                                //一卡通push住户设备权限信息时住户信息为空，先存储住户信息在使用RabbitMQ处理住户设备权限信息

                                iSmartCardUserInfoServiceClient.handleSmartCardPushDeviceAuth(
                                        userPhone,userEmail, projectId, projectInfo.getIsSmartCommunity(), appUserGetDeviceAuthVOS);
                            };
                            break;
                        default:
                            break;
                    }
                }

                //更新push表中已完成解析的数据的状态
                this.setSyncPushDataResolvedById(smartCardPushPO);

            } catch (Exception e) {
                LOG.error(String.format("处理一卡通推送给云端的用户设备权限失败,%s",syncData), e);
               continue;
            }


        }
        return true;
    }


    /**
     * <desc>
     *      与旺龙一卡通对接-整理解析存于push表的中的通行信息数据
     * <desc/>
     *
     * @param pushTableRecordData 通行信息解析传输对象
     * @return
     * @author LewisLouis
     * @createDate 2019-01-23
     *
     * 一卡通上传的data数据格式示例：
     * [{"projectId":"05041276","deviceUnique":"0504127630010","modifyDate":"1505909016893","deviceName":"15312","deviceType":"3","dataOperType":3}]
     */
    private boolean handleAnalysisPassRecord(List<SmartCardPushPO> pushTableRecordData) throws InterruptedException {
        if (pushTableRecordData.isEmpty()) {
            return true;
        }
        //延迟5秒更新通行记录，避免一卡通与云端同时更新造成通行记录重复问题
        Thread.sleep(5000);
        String projectId = pushTableRecordData.get(0).getProjectId();
        Map<String,String> deviceInfos = new HashMap<>(); //设备信息《deviceUnique,deviceName》
        List<TimeTaskDevicePassRecordPO> recordPOS = new ArrayList<>();
        //遍历，获取同步表中一卡通push的数据，按云端系统现有PO进行解析最后入库
        for (SmartCardPushPO smartCardPushPO :pushTableRecordData) {
            //同步的数据
            String syncData = smartCardPushPO.getSyncData();

            try {
                boolean needSave = true;
                //解析
                SmartCardSyncDataPullRecordDTO recordDTO =
                        JSON.parseObject(syncData, SmartCardSyncDataPullRecordDTO.class);
                if (recordDTO == null) {
                    LOG.info(String.format("解析一卡通推送给云端的通行记录数据失败,%s",syncData));
                    needSave = false;
                }
                if (null == recordDTO || (StringUtils.isBlank(recordDTO.getDeviceUnique()))
                        || (StringUtils.isBlank(recordDTO.getPassTime()))){
                    LOG.info(String.format("一卡通上传给云端的通行记录不合法,放弃处理,%s",JSON.toJSONString(recordDTO)));
                    needSave = false;
                }

                String recordProjectId = StringHandlerUtil.getProjectIdByDeviceUnique(recordDTO.getDeviceUnique());
                //设备Unique中的项目Id和当前数据的项目Id匹配时（防止一卡通在离线时随意更新项目导致设备与项目不匹配），才进行更新
                if (!StringHandlerUtil.compareStrIgnoreCaseWithOutEmpty(recordProjectId,projectId)){
                    LOG.info(String.format("一卡通同步到云端的通行记录：%s 不属于项目:%s，放弃处理!",JSON.toJSONString(recordDTO),projectId));
                    needSave = false;
                }
                AppUserInfoPO userInfoPO = null;
                if(recordDTO.getPassType()!= OpenTypeEnum.BY_VISTOR_QRCODE.getType() && recordDTO.getPassType()!=OpenTypeEnum.BY_QRCODE.getType()){
                    SmartCardGetAppUserInfoDTO getAppUserInfoDTO = new SmartCardGetAppUserInfoDTO();
                    getAppUserInfoDTO.setProjectId(projectId);
                    getAppUserInfoDTO.setPhoneNum(recordDTO.getUserPhone());
                    getAppUserInfoDTO.setEmail(recordDTO.getUserEmail());
                    userInfoPO = iSmartCardUserInfoServiceClient.getSmartCardAppUserInfo(getAppUserInfoDTO);
//                    if (null == userInfoPO){
                    //由于物业后台生成的访客二维码中的用户手机号为00000000000或为11位随机字符串，故在此需作以下处理，否则通行记录无法保存至time_task_device_pass_record中
//                        if(recordDTO.getPassType()== OpenTypeEnum.BY_VISTOR_QRCODE.getType()){
//                            userInfoPO.setUserId("");
//                        }
//                        else{
//                            LOG.error(String.format("一卡通同步到云端的通行记录：%s 没有在对应项目中找到用户信息，放弃处理!",JSON.toJSONString(recordDTO),projectId));
//                            needSave = false;
//                        }
//                    }
                }

                if (needSave){
                    TimeTaskDevicePassRecordPO po = new TimeTaskDevicePassRecordPO();
                    po.setPdId(LogicIdUtil.bussinessId());
                    if(OpenTypeEnum.BY_QRCODE.getType() == recordDTO.getPassType() &&
                            StringUtils.isNotBlank(recordDTO.getUserPhone())){
                        if(!StringHandlerUtil.checkIsPhone(recordDTO.getUserPhone())){
                            recordDTO.setUserPhone(recordDTO.getUserPhone().substring(recordDTO.getUserPhone().length()-8,recordDTO.getUserPhone().length()));
                        }
                        String userId = iSmartCardUserInfoServiceClient.getUserIdByUid(recordDTO.getUserPhone(), projectId);
                        if(StringUtils.isNotBlank(userId)) {
                            if (iPropertyEquipServiceClient.checkOwnerRecordExists(userId, projectId,
                                    DateUtil.fomatDate(DateUtil.formatLong(Long.parseLong(recordDTO.getPassTime())), DateUtil.DATE_FORMAT_TYPE1)
                                    , recordDTO.getDeviceUnique()) > 0) {
                                continue;
                            }
                        }
                        //sdk二维码
                        if(StringUtils.isBlank(userId) && iPropertyEquipServiceClient.checkSDKQrcodeRecordExists(recordDTO.getUserPhone(),projectId,
                                DateUtil.fomatDate(DateUtil.formatLong(Long.parseLong(recordDTO.getPassTime())),DateUtil.DATE_FORMAT_TYPE1),recordDTO.getDeviceUnique(),8) > 0){
                            continue;
                        }
                        if(StringUtils.isBlank(userId)){
                            po.setQrcodeSource(2);
                        }
                        po.setUserId(userId);
                    }else if(OpenTypeEnum.BY_VISTOR_QRCODE.getType() == recordDTO.getPassType() &&
                            StringUtils.isNotBlank(recordDTO.getUserPhone())){
                        if(!StringHandlerUtil.checkIsPhone(recordDTO.getUserPhone())){
                            recordDTO.setUserPhone(recordDTO.getUserPhone().substring(recordDTO.getUserPhone().length()-8,recordDTO.getUserPhone().length()));
                        }
                        //访客二维码
                        String passId = iSmartCardUserInfoServiceClient.getPassIdByQrcodeInfo(recordDTO.getUserPhone(),projectId,
                                DateUtil.fomatDate(DateUtil.formatLong(Long.parseLong(recordDTO.getPassTime())),DateUtil.DATE_FORMAT_TYPE1));
                        if(StringUtils.isNotBlank(passId)) {
                            if (iPropertyEquipServiceClient.checkVisitorExists(passId,DateUtil.fomatDate(DateUtil.formatLong(Long.parseLong(recordDTO.getPassTime())),DateUtil.DATE_FORMAT_TYPE1),recordDTO.getDeviceUnique()) > 0) {
                                continue;
                            }
                            po.setPassId(passId);
                        }
                        //sdk二维码
                        if(StringUtils.isBlank(passId) && iPropertyEquipServiceClient.checkSDKQrcodeRecordExists(recordDTO.getUserPhone(),projectId,
                                DateUtil.fomatDate(DateUtil.formatLong(Long.parseLong(recordDTO.getPassTime())),DateUtil.DATE_FORMAT_TYPE1),recordDTO.getDeviceUnique(),11) > 0){
                            continue;
                        }
                        if(StringUtils.isBlank(passId)) {
                            po.setQrcodeSource(2);
                        }
                        po.setUserId(recordDTO.getUserPhone());
                    } else if(recordDTO.getPassType()!= OpenTypeEnum.BY_VISTOR_QRCODE.getType() && userInfoPO!=null){
                        po.setUserId(userInfoPO.getUserId());
                    }
                    po.setProjectId(projectId);
                    po.setDeviceUnique(recordDTO.getDeviceUnique());
                    po.setPassTime(DateUtil.formatLong(Long.parseLong(recordDTO.getPassTime())));
                    String deviceName = deviceInfos.get(recordDTO.getDeviceUnique());
                    if (StringUtils.isBlank(deviceName)){
                        PropertyEquipGetVO equipGetVO =  iPropertyEquipServiceClient.getByDeviceUnique(recordDTO.getDeviceUnique());
                        if (null != equipGetVO){
                            deviceName = equipGetVO.getDeviceName();
                        }
                        deviceInfos.put(recordDTO.getDeviceUnique(),deviceName);
                    }
                    po.setDeviceName(deviceName);
                    po.setOpenType(recordDTO.getPassType());
                    po.setOpenCount(1);
                    po.setStatus(DataStatusEnum.NORMAL.getType());
                    po.setUploadTime(new Date());
                    po.setCreateTime(po.getUploadTime());
                    po.setSynchro(0);
                    po.setIsOpen(0);
                    po.setDeviceType(recordDTO.getDeviceType());
                    if(iPropertyEquipServiceClient.checkEquipExists(recordDTO.getDeviceUnique(),StringHandlerUtil.getDeviceTypeByDeviceUnique(recordDTO.getDeviceUnique())) > 0){
                        recordPOS.add(po);
                    }
                    po.setSystemType(2);
                    recordPOS.add(po);
                }
            } catch (Exception e) {
                LOG.error(String.format("处理一卡通推送给云端的通行记录数据失败,%s",syncData), e);
                continue;
            }
        }  //循环结束

        try {
            if (!recordPOS.isEmpty()){
                iSmartCardEquipRecordServiceClient.addEquipRecordInfos(recordPOS);
            }


            for (SmartCardPushPO smartCardPushPO :pushTableRecordData) {
                //更新push表中已完成解析的数据的状态
                this.setSyncPushDataResolvedById(smartCardPushPO);
            }
        } catch (Exception e) {
            LOG.error(String.format("处理一卡通推送给云端的通行记录数据失败,%s",JSON.toJSONString(pushTableRecordData)), e);
            return false;
        }
        return true;
    }

    /**
     * <desc>
     *      更新push表中已完成解析的数据的状态
     * <desc/>
     *
     * @param smartCardPushPO 同步数据
     * @return
     * @author zhangs
     * @createDate 2017/11/15
     */
    private void setSyncPushDataResolvedById(SmartCardPushPO smartCardPushPO) {
        String tableName = String.format("%s%s",PlatformConstants.SMARTCARD_TABLENAME_PREFIX_PUSH,smartCardPushPO.getProjectId());
//        smartCardPushPO.setTableName(PlatformConstants.SMARTCARD_TABLENAME_PREFIX_PUSH + projectId);
//        smartCardPushPO.setSolveMark(PlatformConstants.SMARTCARD_SYNC_DATA_STATUS_ALREADY);
        iSmartCardSyncDataServiceClient.setSyncPushDataResolvedById(tableName,smartCardPushPO.getId());
    }


    /**
    * <desc>
    *      判断push给云端的数据与pull表中相比是否是最新数据.
    * </desc>
    *
    * @param tableName pull表名
    * @param needCheckSmartCardPushInfo 需要检查是否是最新数据
    * @return 是否是最新数据 true 是;  false 否；
    * @author LewisLouis
    * @createDate 2017-12-26
    */
    private boolean isLatestData(String tableName,SmartCardPushPO needCheckSmartCardPushInfo){
        SmartCardPullPO qryConSmartCardPullPO = new SmartCardPullPO();
        qryConSmartCardPullPO.setDataUid(needCheckSmartCardPushInfo.getDataUid());
        qryConSmartCardPullPO.setDataType(needCheckSmartCardPushInfo.getDataType());
        List<SmartCardPullPO> smartCardPullPOS = iSmartCardSyncDataServiceClient.getPullData(tableName,qryConSmartCardPullPO);
        if (smartCardPullPOS != null && !smartCardPullPOS.isEmpty()
                && smartCardPullPOS.get(0).getUpdateTime().after(needCheckSmartCardPushInfo.getUpdateTime())) {
           // LOG.info(String.format("不是最新数据:%s,最新的数据是:%s",JSON.toJSONString(smartCardPullPOS.get(0))));
            return false;
        }
       // LOG.info(String.format("是最新的数据:%s",JSON.toJSONString(needCheckSmartCardPushInfo)));
        return true;


    }

}
